# -*- coding: utf-8 -*-

import logging
import os
import threading
import time

from app.core.config import Config
from app.helper.helper import logs_path


class Log:
    """
    日志操作类
    使用 l = Log.init()
    """

    _instance_lock = threading.Lock()

    def __init__(self):
        self.config = Config.init()

        self._log_level = self.config.get("log", "level")

        self._formatter = "%(asctime)s-%(filename)s [line:%(lineno)d]-%(levelname)s:%(message)s"

    def __new__(cls, *args, **kwargs):
        if not hasattr(cls, '_instance'):
            with cls._instance_lock:
                if not hasattr(cls, '_instance'):
                    cls._instance = object.__new__(cls)

                    # 实例化对象后增加私有属性(必须放在后面)
                    cls._log = cls()._get_logger()

        return cls._instance

    @classmethod
    def init(cls):
        """初始化返回原生logging，可以直接调用使用"""
        return cls()._log

    def _get_logger(self):
        """获取logger类实例"""

        logger = logging.getLogger()

        logger.setLevel(logging.DEBUG)

        logger.addHandler(self._get_log_file_handler())
        logger.addHandler(self._get_log_stream_handler())

        return logger

    def _get_log_file_handler(self):
        """
        创建一个handler，用于写入日志文件
        :return: FileHandler
        """

        # 第一步，创建一个handler
        log_name = time.strftime('%Y-%m-%d', time.localtime(time.time()))
        logfile = os.path.join(logs_path(), log_name + '.log')

        fh = logging.FileHandler(logfile)
        fh.setLevel(self._log_level)

        # 第二步，定义handler的输出格式
        formatter = logging.Formatter(self._formatter)
        fh.setFormatter(formatter)

        return fh

    def _get_log_stream_handler(self):
        """
        创建一个handler，用于输出到控制台
        :return: StreamHandler
        """

        # 第一步，创建一个handler
        ch = logging.StreamHandler()
        ch.setLevel(self._log_level)

        # 第二步，定义handler的输出格式
        formatter = logging.Formatter(self._formatter)
        ch.setFormatter(formatter)

        return ch
